/*
 * vm.java
 *
 * Created on 02.03.2010, 20:01:08
 */

package vm;

import java.io.IOException;
import javax.swing.JButton;
import vm.help.*;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JPopupMenu.Separator;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileNameExtensionFilter;

/**
 *
 * @author Peer
 */
public class vm extends JFrame implements ActionListener, WindowListener, ChangeListener {

    String version ="2012.06.21";
    StackMachine currentMachine = null;

    // <editor-fold defaultstate="collapsed" desc="Busy Icon Handling">
    ImageIcon idleIcon = new ImageIcon(getClass().getResource("/resources/busyicons/idle-icon.png"));
    Timer busy = new Timer(100, new ActionListener(){

        int pos = 0;
        
        ImageIcon[] pics = new ImageIcon[15];
        {
            for(int i = 0;i<pics.length ;i++) {
            pics[i] = new ImageIcon(getClass().getResource("/resources/busyicons/busy-icon"+i+".png"));
            }
        }

        public void actionPerformed(ActionEvent e) {
            statuslabel.setIcon(pics[pos]);
            pos = ++pos%15;
        }
    });// </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Inner Class lafListener">
    class lafListener implements ActionListener {

        vm parent;
        HashMap<String,String> lafTable = new HashMap<String,String>();

        public lafListener(vm parent) {
            this.parent = parent;
        }

        void addLaf(String name, String klasse) {
            lafTable.put(name, klasse);
        }

        public void actionPerformed(ActionEvent e) {
            try {
                UIManager.setLookAndFeel(lafTable.get(e.getActionCommand()));
                SwingUtilities.updateComponentTreeUI(parent);
                SwingUtilities.updateComponentTreeUI(PopupMenu);
               //parent.pack();

                parent.broadcastStatus("<html>Look & Feel changed to: <i>"+e.getActionCommand()+"</i></html>");
            } catch (Exception ex) {
                Logger.getLogger(vm.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }// </editor-fold>


    // <editor-fold defaultstate="collapsed" desc="Constructor">
    /** Creates new form vm */
    public vm() {
        File dir = new File("machines");
        if(!dir.exists())
            dir.mkdir();
        initComponents();
        try {
            ButtonGroup bGroup = new ButtonGroup();
            JRadioButtonMenuItem tempMenu;
            lafListener listener = new lafListener(this);
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                listener.addLaf(info.getName(), info.getClassName());
                tempMenu = new JRadioButtonMenuItem(info.getName());
                tempMenu.addActionListener(listener);
                bGroup.add(tempMenu);
                lafMenu.add(tempMenu);
                if(info.getClassName().equals(UIManager.getSystemLookAndFeelClassName())) {
                    tempMenu.setSelected(true);
                    UIManager.setLookAndFeel(info.getClassName());
                    SwingUtilities.updateComponentTreeUI(this);
                    SwingUtilities.updateComponentTreeUI(PopupMenu);
                }
            }
        } catch (Exception ex) {
            Logger.getLogger(vm.class.getName()).log(Level.SEVERE, null, ex);
        }
    } //</editor-fold>

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        PopupMenu = new JPopupMenu();
        PopResetAndRunMenuItem = new JMenuItem();
        PopSaveMenuItem = new JMenuItem();
        PopRenameMenuItem = new JMenuItem();
        jSeparator10 = new Separator();
        PopCloseMenuItem = new JMenuItem();
        viewPane = new JTabbedPane();
        statuslabel = new JLabel();
        ToolBar = new JToolBar();
        openButton = new JButton();
        saveButton = new JButton();
        jSeparator6 = new JToolBar.Separator();
        undoButton = new JButton();
        redoButton = new JButton();
        jSeparator8 = new JToolBar.Separator();
        runStepButton = new JButton();
        resetAndRunButton = new JButton();
        runButton = new JButton();
        runToCursorButton = new JButton();
        resetButton = new JButton();
        jSeparator7 = new JToolBar.Separator();
        cycleLimitLabel = new JLabel();

        maxCycles = new JSpinner(); // NOI18N
        timeoutLabel = new JLabel();
        timeout = new JSpinner();
        MenuBar = new JMenuBar();
        jMenu1 = new JMenu();
        newHVMMenuItem = new JMenuItem();
        newSHVMMenuItem = new JMenuItem();
        openMenuItem = new JMenuItem();
        saveMenuItem = new JMenuItem();
        closeCurrentMenuItem = new JMenuItem();
        jSeparator3 = new Separator();
        propertiesMenuItem = new JMenuItem();
        jSeparator1 = new Separator();
        quitMenuItem = new JMenuItem();
        jMenu2 = new JMenu();
        undoMenuItem = new JMenuItem();
        redoMenuItem = new JMenuItem();
        jSeparator4 = new Separator();
        cutMenuItem = new JMenuItem();
        copyMenuItem = new JMenuItem();
        pasteMenuItem = new JMenuItem();
        jMenu4 = new JMenu();
        runStepMenuItem = new JMenuItem();
        resetAndRunMenuItem = new JMenuItem();
        runMenuItem = new JMenuItem();
        runToCursorMenuItem = new JMenuItem();
        jSeparator9 = new Separator();
        resetMenuItem = new JMenuItem();
        jMenu3 = new JMenu();
        numberInputMenuItem = new JMenuItem();
        asciiInputMenuItem = new JMenuItem();
        jSeparator2 = new Separator();
        clearInputMenuItem = new JMenuItem();
        lafMenu = new JMenu();
        jMenu5 = new JMenu();
        helpHVMMenuItem = new JMenuItem();
        helpSHVMMenuItem = new JMenuItem();
        jSeparator5 = new Separator();
        aboutMenuItem = new JMenuItem();

        PopResetAndRunMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/runProject.png"))); // NOI18N
        PopResetAndRunMenuItem.setText("Run (with reset)");
        PopResetAndRunMenuItem.addActionListener(this);
        PopupMenu.add(PopResetAndRunMenuItem);

        PopSaveMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/saveAll.gif"))); // NOI18N
        PopSaveMenuItem.setText("Save");
        PopSaveMenuItem.addActionListener(this);
        PopupMenu.add(PopSaveMenuItem);

        PopRenameMenuItem.setText("Rename");
        PopRenameMenuItem.addActionListener(this);
        PopupMenu.add(PopRenameMenuItem);
        PopupMenu.add(jSeparator10);

        PopCloseMenuItem.setText("Close");
        PopCloseMenuItem.addActionListener(this);
        PopupMenu.add(PopCloseMenuItem);

        setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        setTitle("HVM/SHVM IDE");
        setMinimumSize(new Dimension(640, 480));
        setName("mainWindow"); // NOI18N
        addWindowListener(this);

        viewPane.setTabPlacement(JTabbedPane.BOTTOM);
        viewPane.addChangeListener(this);
        getContentPane().add(viewPane, BorderLayout.CENTER);

        statuslabel.setHorizontalAlignment(SwingConstants.TRAILING);
        statuslabel.setIcon(idleIcon);
        statuslabel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
        statuslabel.setHorizontalTextPosition(SwingConstants.LEADING);
        getContentPane().add(statuslabel, BorderLayout.PAGE_END);

        ToolBar.setFloatable(false);
        ToolBar.setRollover(true);
        ToolBar.setFocusable(false);

        openButton.setIcon(new ImageIcon(getClass().getResource("/resources/openProject24.png"))); // NOI18N
        openButton.setToolTipText("Open a previously saved VM");
        openButton.setFocusable(false);
        openButton.addActionListener(this);
        ToolBar.add(openButton);

        saveButton.setIcon(new ImageIcon(getClass().getResource("/resources/saveAll24.gif"))); // NOI18N
        saveButton.setEnabled(false);
        saveButton.setFocusable(false);
        saveButton.setHorizontalTextPosition(SwingConstants.CENTER);
        saveButton.setVerticalTextPosition(SwingConstants.BOTTOM);
        saveButton.addActionListener(this);
        ToolBar.add(saveButton);

        jSeparator6.setSeparatorSize(new Dimension(5,openButton.getPreferredSize().height-4));
        ToolBar.add(jSeparator6);

        undoButton.setIcon(new ImageIcon(getClass().getResource("/resources/undo24.gif"))); // NOI18N
        undoButton.setToolTipText("Undo");
        undoButton.setEnabled(false);
        undoButton.setFocusable(false);
        undoButton.setHorizontalTextPosition(SwingConstants.CENTER);
        undoButton.setVerticalTextPosition(SwingConstants.BOTTOM);
        undoButton.addActionListener(this);
        ToolBar.add(undoButton);

        redoButton.setIcon(new ImageIcon(getClass().getResource("/resources/redo24.gif"))); // NOI18N
        redoButton.setToolTipText("Redo");
        redoButton.setEnabled(false);
        redoButton.setFocusable(false);
        redoButton.setHorizontalTextPosition(SwingConstants.CENTER);
        redoButton.setVerticalTextPosition(SwingConstants.BOTTOM);
        redoButton.addActionListener(this);
        ToolBar.add(redoButton);

        jSeparator8.setSeparatorSize(jSeparator6.getSeparatorSize());
        ToolBar.add(jSeparator8);

        runStepButton.setIcon(new ImageIcon(getClass().getResource("/resources/StepInto24.gif"))); // NOI18N
        runStepButton.setToolTipText("Run one Step");
        runStepButton.setEnabled(false);
        runStepButton.setFocusable(false);
        runStepButton.setHorizontalTextPosition(SwingConstants.CENTER);
        runStepButton.setVerticalTextPosition(SwingConstants.BOTTOM);
        runStepButton.addActionListener(this);
        ToolBar.add(runStepButton);

        resetAndRunButton.setIcon(new ImageIcon(getClass().getResource("/resources/runProject24.png"))); // NOI18N
        resetAndRunButton.setToolTipText("Run with Reset");
        resetAndRunButton.setEnabled(false);
        resetAndRunButton.setFocusable(false);
        resetAndRunButton.setHorizontalTextPosition(SwingConstants.CENTER);
        resetAndRunButton.setVerticalTextPosition(SwingConstants.BOTTOM);
        resetAndRunButton.addActionListener(this);
        ToolBar.add(resetAndRunButton);

        runButton.setIcon(new ImageIcon(getClass().getResource("/resources/Continue24.gif"))); // NOI18N
        runButton.setToolTipText("Continue");
        runButton.setEnabled(false);
        runButton.setFocusable(false);
        runButton.setHorizontalTextPosition(SwingConstants.CENTER);
        runButton.setVerticalTextPosition(SwingConstants.BOTTOM);
        runButton.addActionListener(this);
        ToolBar.add(runButton);

        runToCursorButton.setIcon(new ImageIcon(getClass().getResource("/resources/RunToCursor24.gif"))); // NOI18N
        runToCursorButton.setToolTipText("Run to Cursor");
        runToCursorButton.setEnabled(false);
        runToCursorButton.setFocusable(false);
        runToCursorButton.setHorizontalTextPosition(SwingConstants.CENTER);
        runToCursorButton.setVerticalTextPosition(SwingConstants.BOTTOM);
        runToCursorButton.addActionListener(this);
        ToolBar.add(runToCursorButton);

        resetButton.setIcon(new ImageIcon(getClass().getResource("/resources/Kill24.gif"))); // NOI18N
        resetButton.setToolTipText("Stop/Reset");
        resetButton.setEnabled(false);
        resetButton.setFocusable(false);
        resetButton.setHorizontalTextPosition(SwingConstants.CENTER);
        resetButton.setVerticalTextPosition(SwingConstants.BOTTOM);
        resetButton.addActionListener(this);
        ToolBar.add(resetButton);

        jSeparator7.setSeparatorSize(jSeparator6.getSeparatorSize());
        ToolBar.add(jSeparator7);

        cycleLimitLabel.setHorizontalAlignment(SwingConstants.CENTER);
        cycleLimitLabel.setLabelFor(maxCycles);
        cycleLimitLabel.setText("Cycle limit:");
        cycleLimitLabel.setToolTipText("Maximum Number of allowed Cycles");
        cycleLimitLabel.setBorder(BorderFactory.createEmptyBorder(1, 10, 1, 5));
        ToolBar.add(cycleLimitLabel);
        maxCycles.setModel(new SpinnerNumberModel(10000, 5000, 100000, 5000));
        maxCycles.setMaximumSize(new Dimension(79, 20));
        ToolBar.add(maxCycles);

        timeoutLabel.setText("Timeout (ms):");
        timeoutLabel.setToolTipText("Timeout between Steps when running the Program");
        timeoutLabel.setBorder(BorderFactory.createEmptyBorder(1, 10, 1, 5));
        ToolBar.add(timeoutLabel);

        timeout.setModel(new SpinnerNumberModel(0, 0, 5000, 100));
        timeout.setMaximumSize(new Dimension(63, 20));
        ToolBar.add(timeout);

        getContentPane().add(ToolBar, BorderLayout.NORTH);

        jMenu1.setText("File");

        newHVMMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK));
        newHVMMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/newFile.png"))); // NOI18N
        newHVMMenuItem.setText("New HVM");
        newHVMMenuItem.addActionListener(this);
        jMenu1.add(newHVMMenuItem);

        newSHVMMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.SHIFT_MASK | InputEvent.CTRL_MASK));
        newSHVMMenuItem.setIcon(newHVMMenuItem.getIcon());
        newSHVMMenuItem.setText("New SHVM");
        newSHVMMenuItem.addActionListener(this);
        jMenu1.add(newSHVMMenuItem);

        openMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));
        openMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/openProject.png"))); // NOI18N
        openMenuItem.setText("Open");
        openMenuItem.addActionListener(this);
        jMenu1.add(openMenuItem);

        saveMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK));
        saveMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/saveAll.gif"))); // NOI18N
        saveMenuItem.setText("Save current Machine");
        saveMenuItem.setEnabled(false);
        saveMenuItem.addActionListener(this);
        jMenu1.add(saveMenuItem);

        closeCurrentMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK));
        closeCurrentMenuItem.setText("Close current Machine");
        closeCurrentMenuItem.setEnabled(false);
        closeCurrentMenuItem.addActionListener(this);
        jMenu1.add(closeCurrentMenuItem);
        jMenu1.add(jSeparator3);

        propertiesMenuItem.setText("VM Properties");
        jMenu1.add(propertiesMenuItem);
        jMenu1.add(jSeparator1);

        quitMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_MASK));
        quitMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/no.png"))); // NOI18N
        quitMenuItem.setText("Quit");
        quitMenuItem.addActionListener(this);
        jMenu1.add(quitMenuItem);

        MenuBar.add(jMenu1);

        jMenu2.setText("Edit");

        undoMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_MASK));
        undoMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/undo.gif"))); // NOI18N
        undoMenuItem.setText("Undo");
        undoMenuItem.setEnabled(false);
        undoMenuItem.addActionListener(this);
        jMenu2.add(undoMenuItem);

        redoMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_MASK));
        redoMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/redo.gif"))); // NOI18N
        redoMenuItem.setText("Redo");
        redoMenuItem.setEnabled(false);
        redoMenuItem.addActionListener(this);
        jMenu2.add(redoMenuItem);
        jMenu2.add(jSeparator4);

        cutMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK));
        cutMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/cut.gif"))); // NOI18N
        cutMenuItem.setText("Cut");
        cutMenuItem.setEnabled(false);
        cutMenuItem.addActionListener(this);
        jMenu2.add(cutMenuItem);

        copyMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK));
        copyMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/copy.gif"))); // NOI18N
        copyMenuItem.setText("Copy");
        copyMenuItem.setEnabled(false);
        copyMenuItem.addActionListener(this);
        jMenu2.add(copyMenuItem);

        pasteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK));
        pasteMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/paste.gif"))); // NOI18N
        pasteMenuItem.setText("Paste");
        pasteMenuItem.setEnabled(false);
        pasteMenuItem.addActionListener(this);
        jMenu2.add(pasteMenuItem);

        MenuBar.add(jMenu2);

        jMenu4.setText("Run");

        runStepMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/StepInto.gif"))); // NOI18N
        runStepMenuItem.setText("Run one Step");
        runStepMenuItem.setEnabled(false);
        runStepMenuItem.addActionListener(this);
        jMenu4.add(runStepMenuItem);

        resetAndRunMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/runProject.png"))); // NOI18N
        resetAndRunMenuItem.setText("Run (with reset)");
        resetAndRunMenuItem.setEnabled(false);
        resetAndRunMenuItem.addActionListener(this);
        jMenu4.add(resetAndRunMenuItem);

        runMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/Continue.gif"))); // NOI18N
        runMenuItem.setText("Run (continue)");
        runMenuItem.setEnabled(false);
        runMenuItem.addActionListener(this);
        jMenu4.add(runMenuItem);

        runToCursorMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/RunToCursor.gif"))); // NOI18N
        runToCursorMenuItem.setText("Run to Cursor");
        runToCursorMenuItem.setEnabled(false);
        runToCursorMenuItem.addActionListener(this);
        jMenu4.add(runToCursorMenuItem);
        jMenu4.add(jSeparator9);

        resetMenuItem.setIcon(new ImageIcon(getClass().getResource("/resources/Kill.gif"))); // NOI18N
        resetMenuItem.setText("Stop/Reset");
        resetMenuItem.setEnabled(false);
        resetMenuItem.addActionListener(this);
        jMenu4.add(resetMenuItem);

        MenuBar.add(jMenu4);

        jMenu3.setText("Input");

        numberInputMenuItem.setText("Load Number Sequence");
        numberInputMenuItem.setEnabled(false);
        numberInputMenuItem.addActionListener(this);
        jMenu3.add(numberInputMenuItem);

        asciiInputMenuItem.setText("Load ASCII String");
        asciiInputMenuItem.setEnabled(false);
        asciiInputMenuItem.addActionListener(this);
        jMenu3.add(asciiInputMenuItem);
        jMenu3.add(jSeparator2);

        clearInputMenuItem.setText("Clear Input");
        clearInputMenuItem.setEnabled(false);
        clearInputMenuItem.addActionListener(this);
        jMenu3.add(clearInputMenuItem);

        MenuBar.add(jMenu3);

        lafMenu.setText("Look & Feel");
        MenuBar.add(lafMenu);

        jMenu5.setText("Help");

        helpHVMMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
        helpHVMMenuItem.setText("HVM");
        helpHVMMenuItem.addActionListener(this);
        jMenu5.add(helpHVMMenuItem);

        helpSHVMMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, InputEvent.SHIFT_MASK));
        helpSHVMMenuItem.setText("SVHM");
        helpSHVMMenuItem.addActionListener(this);
        jMenu5.add(helpSHVMMenuItem);
        jMenu5.add(jSeparator5);

        aboutMenuItem.setText("About...");
        aboutMenuItem.addActionListener(this);
        jMenu5.add(aboutMenuItem);

        MenuBar.add(jMenu5);

        setJMenuBar(MenuBar);

        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width-656)/2, (screenSize.height-518)/2, 656, 518);
    }

    // Code for dispatching events from components to event handlers.

    public void actionPerformed(java.awt.event.ActionEvent evt) {
        if (evt.getSource() == openButton) {
            vm.this.openButtonActionPerformed(evt);
        }
        else if (evt.getSource() == saveButton) {
            vm.this.saveButtonActionPerformed(evt);
        }
        else if (evt.getSource() == undoButton) {
            vm.this.undoButtonActionPerformed(evt);
        }
        else if (evt.getSource() == redoButton) {
            vm.this.redoButtonActionPerformed(evt);
        }
        else if (evt.getSource() == runStepButton) {
            vm.this.runStepButtonActionPerformed(evt);
        }
        else if (evt.getSource() == resetAndRunButton) {
            vm.this.resetAndRunButtonActionPerformed(evt);
        }
        else if (evt.getSource() == runButton) {
            vm.this.runButtonActionPerformed(evt);
        }
        else if (evt.getSource() == runToCursorButton) {
            vm.this.runToCursorButtonActionPerformed(evt);
        }
        else if (evt.getSource() == resetButton) {
            vm.this.resetButtonActionPerformed(evt);
        }
        else if (evt.getSource() == PopResetAndRunMenuItem) {
            vm.this.PopResetAndRunMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == PopSaveMenuItem) {
            vm.this.PopSaveMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == PopRenameMenuItem) {
            vm.this.PopRenameMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == PopCloseMenuItem) {
            vm.this.PopCloseMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == newHVMMenuItem) {
            vm.this.newHVMMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == newSHVMMenuItem) {
            vm.this.newSHVMMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == openMenuItem) {
            vm.this.openMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == saveMenuItem) {
            vm.this.saveMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == closeCurrentMenuItem) {
            vm.this.closeCurrentMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == quitMenuItem) {
            vm.this.quitMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == undoMenuItem) {
            vm.this.undoMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == redoMenuItem) {
            vm.this.redoMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == cutMenuItem) {
            vm.this.cutMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == copyMenuItem) {
            vm.this.copyMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == pasteMenuItem) {
            vm.this.pasteMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == runStepMenuItem) {
            vm.this.runStepMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == resetAndRunMenuItem) {
            vm.this.resetAndRunMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == runMenuItem) {
            vm.this.runMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == runToCursorMenuItem) {
            vm.this.runToCursorMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == resetMenuItem) {
            vm.this.resetMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == numberInputMenuItem) {
            vm.this.numberInputMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == asciiInputMenuItem) {
            vm.this.asciiInputMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == clearInputMenuItem) {
            vm.this.clearInputMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == helpHVMMenuItem) {
            vm.this.helpHVMMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == helpSHVMMenuItem) {
            vm.this.helpSHVMMenuItemActionPerformed(evt);
        }
        else if (evt.getSource() == aboutMenuItem) {
            vm.this.aboutMenuItemActionPerformed(evt);
        }
    }

    public void windowActivated(java.awt.event.WindowEvent evt) {
    }

    public void windowClosed(java.awt.event.WindowEvent evt) {
    }

    public void windowClosing(java.awt.event.WindowEvent evt) {
        if (evt.getSource() == vm.this) {
            vm.this.formWindowClosing(evt);
        }
    }

    public void windowDeactivated(java.awt.event.WindowEvent evt) {
    }

    public void windowDeiconified(java.awt.event.WindowEvent evt) {
    }

    public void windowIconified(java.awt.event.WindowEvent evt) {
    }

    public void windowOpened(java.awt.event.WindowEvent evt) {
    }

    public void stateChanged(javax.swing.event.ChangeEvent evt) {
        if (evt.getSource() == viewPane) {
            vm.this.viewPaneStateChanged(evt);
        }
    }// </editor-fold>//GEN-END:initComponents

    // <editor-fold defaultstate="collapsed" desc="Event Handling">
    private void formWindowClosing(WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        closeApp();
    }//GEN-LAST:event_formWindowClosing

    private void viewPaneStateChanged(ChangeEvent evt) {//GEN-FIRST:event_viewPaneStateChanged
        int selected = viewPane.getSelectedIndex();
        if(selected==-1) {
            currentMachine = null;
            enableMenus(false);
            setChanged(false);
            viewPane.setComponentPopupMenu(null);
        }
        else {
            currentMachine = (StackMachine)viewPane.getComponent(selected);
            enableMenus(true);
            currentMachine.updateUndoRedo();
            currentMachine.setFocus();
            viewPane.setComponentPopupMenu(PopupMenu);
        }
    }//GEN-LAST:event_viewPaneStateChanged

    private void aboutMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_aboutMenuItemActionPerformed
        setBusy(true,"<html>Showing the <i>About</i> window</html>");
        JOptionPane.showConfirmDialog(this, //parent
                new JLabel("<html><center><font size=+1 color='#dd7700'>IDE for HVM and SHVM</font><br>(alpha "+version+")</center></html>"),
                "Info", //title
                JOptionPane.DEFAULT_OPTION, //option type
                JOptionPane.INFORMATION_MESSAGE); //message type
        setBusy(false,"");
        //JOptionPane.showOptionDialog(this, "IDE for HVM and SHVM\n(pre alpha)", "Info", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, options[0]);
    }//GEN-LAST:event_aboutMenuItemActionPerformed

    private void quitMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_quitMenuItemActionPerformed
        closeApp();
    }//GEN-LAST:event_quitMenuItemActionPerformed

    private void numberInputMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_numberInputMenuItemActionPerformed
        setBusy(true,"Inputting number sequence...");
        String in = JOptionPane.showInputDialog(this,
                                                "Enter number sequence separated!\n (e.g. 1,2,-3,...)",
                                                "Input",
                                                JOptionPane.INFORMATION_MESSAGE);
        if(in!=null&&in.matches("-?[0-9]+(,-?[0-9]+)*")) {
            currentMachine.setInput(in);
            setBusy(false,"<html>Input set to: <i>"+in+"</i></html>");
        }
        else if(in!=null&&in.length()==0)
            setBusy(false,"No Input");
        else if(in!=null)
            setBusy(false,"Error in Input");
        else
            setBusy(false,"Input aborted");
    }//GEN-LAST:event_numberInputMenuItemActionPerformed

    private void asciiInputMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_asciiInputMenuItemActionPerformed
        setBusy(true,"Inputing ASCII string...");
        String in = JOptionPane.showInputDialog(this,
                                                "Enter ASCII string!",
                                                "Input",
                                                JOptionPane.INFORMATION_MESSAGE);
        if(in!=null&&in.length()>0) {
            byte[] chars = in.getBytes();
            StringBuilder input = new StringBuilder("");
            input.append(chars[0]);
            for (int i = 1; i < in.length(); i++) {
                input.append(",");
                input.append(chars[i]);
            }
            setBusy(false,"<html>Input set to: <i>"+input+"</i></html>");
            currentMachine.setInput(input.toString());
        } else if(in!=null)
            setBusy(false,"No Input");
        else
            setBusy(false,"Input aborted");
    }//GEN-LAST:event_asciiInputMenuItemActionPerformed

    private void cutMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_cutMenuItemActionPerformed
        currentMachine.cut();
    }//GEN-LAST:event_cutMenuItemActionPerformed

    private void copyMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_copyMenuItemActionPerformed
        currentMachine.copy();
    }//GEN-LAST:event_copyMenuItemActionPerformed

    private void pasteMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_pasteMenuItemActionPerformed
        currentMachine.paste();
    }//GEN-LAST:event_pasteMenuItemActionPerformed

    private void clearInputMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_clearInputMenuItemActionPerformed
        currentMachine.setInput("");
    }//GEN-LAST:event_clearInputMenuItemActionPerformed

    private void closeCurrentMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_closeCurrentMenuItemActionPerformed
        if(currentMachine.close()) {
            viewPane.remove((Component)currentMachine);
            viewPaneStateChanged(null);
        }
    }//GEN-LAST:event_closeCurrentMenuItemActionPerformed

    private void newHVMMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_newHVMMenuItemActionPerformed
        setBusy(true, "Adding new HVM...");
        String in = JOptionPane.showInputDialog(this, 
                                                "Enter a name for your new machine!",
                                                "New HVM",
                                                JOptionPane.QUESTION_MESSAGE);
        if(machineExists(in,hvm.class)) {
            JOptionPane.showConfirmDialog(this, 
                                          "HVM \""+in+"\" already exists!",
                                          "Already exists",
                                          JOptionPane.DEFAULT_OPTION,
                                          JOptionPane.ERROR_MESSAGE);
            setBusy(false,"");
            return;
        }
        if(in!=null&&in.trim().length()>0&&in.matches("[A-Za-z0-9. ]*")) {
            viewPane.add(in, new hvm(this,in));
            viewPane.setSelectedIndex(viewPane.getComponentCount()-1);
            setBusy(false,"HVM \""+in+"\" added");
        } else if(in!=null){
            JOptionPane.showConfirmDialog(this, 
                                          "You have to enter a valid name!\n (Only [A-Za-z0-9. ] is allowed)",
                                          "No Name",
                                          JOptionPane.DEFAULT_OPTION,
                                          JOptionPane.ERROR_MESSAGE);
            setBusy(false,"Error creating HVM");
        } else
            setBusy(false,"");
    }//GEN-LAST:event_newHVMMenuItemActionPerformed

    private void newSHVMMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_newSHVMMenuItemActionPerformed
        setBusy(true,"Adding new SHVM...");
        String in = JOptionPane.showInputDialog(this,
                                                "Enter a name for your new machine!",
                                                "New SHVM",
                                                JOptionPane.QUESTION_MESSAGE);
        if(machineExists(in,shvm.class)) {
            JOptionPane.showConfirmDialog(this, 
                                          "SHVM \""+in+"\" already exists!",
                                          "Already exists",
                                          JOptionPane.DEFAULT_OPTION,
                                          JOptionPane.ERROR_MESSAGE);
            setBusy(false,"");
            return;
        }
        if(in!=null&&in.trim().length()>0&&in.matches("[A-Za-z0-9. ]*")) {
            viewPane.add(in, new shvm(this,in));
            viewPane.setSelectedIndex(viewPane.getComponentCount()-1);
            setBusy(false,"SHVM \""+in+"\" added");
        } else if(in!=null){
            JOptionPane.showConfirmDialog(this, 
                                          "You have to enter a valid name!\n (Only [A-Za-z0-9. ] is allowed)",
                                          "No Name",
                                          JOptionPane.DEFAULT_OPTION,
                                          JOptionPane.ERROR_MESSAGE);
            setBusy(false,"Error creating SHVM");
        } else
            setBusy(false,"");
    }//GEN-LAST:event_newSHVMMenuItemActionPerformed

    private void helpHVMMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_helpHVMMenuItemActionPerformed
        setBusy(true, "Showing Help for HVM...");
        HelpTable HVMInfoTable = new HelpTable(new HelpTableModelHVM());
        JOptionPane.showOptionDialog(this,
                                     new JScrollPane(HVMInfoTable),
                                     "Help for HVM",
                                     JOptionPane.DEFAULT_OPTION,
                                     JOptionPane.PLAIN_MESSAGE,
                                     null, null, null);
        setBusy(false, "Help closed");
    }//GEN-LAST:event_helpHVMMenuItemActionPerformed

    private void helpSHVMMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_helpSHVMMenuItemActionPerformed
        setBusy(true, "Showing Help for SHVM...");
        HelpTable SHVMInfoTable = new HelpTable(new HelpTableModelSHVM());
        JOptionPane.showOptionDialog(this,
                                     new JScrollPane(SHVMInfoTable),
                                     "Help for SHVM",
                                     JOptionPane.DEFAULT_OPTION,
                                     JOptionPane.PLAIN_MESSAGE,
                                     null, null, null);
        setBusy(false, "Help closed");
    }//GEN-LAST:event_helpSHVMMenuItemActionPerformed

    private void resetAndRunMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_resetAndRunMenuItemActionPerformed
        currentMachine.resetAndRun();
    }//GEN-LAST:event_resetAndRunMenuItemActionPerformed

    private void runMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_runMenuItemActionPerformed
        currentMachine.run();
    }//GEN-LAST:event_runMenuItemActionPerformed

    private void runStepMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_runStepMenuItemActionPerformed
        currentMachine.runStep();
    }//GEN-LAST:event_runStepMenuItemActionPerformed

    private void runToCursorMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_runToCursorMenuItemActionPerformed
        currentMachine.runToCursor();
    }//GEN-LAST:event_runToCursorMenuItemActionPerformed

    private void resetMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_resetMenuItemActionPerformed
        currentMachine.reset();
    }//GEN-LAST:event_resetMenuItemActionPerformed

    private void undoMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_undoMenuItemActionPerformed
        currentMachine.undo();
    }//GEN-LAST:event_undoMenuItemActionPerformed

    private void redoMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_redoMenuItemActionPerformed
        currentMachine.redo();
    }//GEN-LAST:event_redoMenuItemActionPerformed

    private void openButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_openButtonActionPerformed
        openMenuItem.doClick();
    }//GEN-LAST:event_openButtonActionPerformed

    private void saveButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed
        saveMenuItem.doClick();
    }//GEN-LAST:event_saveButtonActionPerformed

    private void resetAndRunButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_resetAndRunButtonActionPerformed
        resetAndRunMenuItem.doClick();
    }//GEN-LAST:event_resetAndRunButtonActionPerformed

    private void runToCursorButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_runToCursorButtonActionPerformed
        runToCursorMenuItem.doClick();
    }//GEN-LAST:event_runToCursorButtonActionPerformed

    private void runButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_runButtonActionPerformed
        runMenuItem.doClick();
    }//GEN-LAST:event_runButtonActionPerformed

    private void runStepButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_runStepButtonActionPerformed
        runStepMenuItem.doClick();
    }//GEN-LAST:event_runStepButtonActionPerformed

    private void resetButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_resetButtonActionPerformed
        resetMenuItem.doClick();
    }//GEN-LAST:event_resetButtonActionPerformed

    private void undoButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_undoButtonActionPerformed
        undoMenuItem.doClick();
    }//GEN-LAST:event_undoButtonActionPerformed

    private void redoButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_redoButtonActionPerformed
        redoMenuItem.doClick();
    }//GEN-LAST:event_redoButtonActionPerformed

    private void saveMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_saveMenuItemActionPerformed
        currentMachine.save();
    }//GEN-LAST:event_saveMenuItemActionPerformed

    private void openMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_openMenuItemActionPerformed
        JFileChooser fc = new JFileChooser("machines");
        fc.setMultiSelectionEnabled(false);
        fc.setFileFilter(new FileNameExtensionFilter("HVM/SHVM Files","hvm","shvm"));
        setBusy(true, "Opening File...");
        if(fc.showOpenDialog(this)==JFileChooser.APPROVE_OPTION) {
            if(!fc.getSelectedFile().getParent().endsWith("machines")) {
                JOptionPane.showConfirmDialog(this,
                                              "File must be in \"machines\" sub dir!", "Wrong Directory",
                                              JOptionPane.DEFAULT_OPTION,
                                              JOptionPane.ERROR_MESSAGE);
                setBusy(false, "File must be in \"machines\" sub dir!");
                return;
            }
            String filename = fc.getSelectedFile().getName().substring(0, fc.getSelectedFile().getName().lastIndexOf("."));
            String ending = fc.getSelectedFile().getName().substring(fc.getSelectedFile().getName().lastIndexOf(".")+1);
            if(ending.equals("hvm")) {
                viewPane.add(filename, new hvm(this,filename));
                setBusy(false,"HVM \""+filename+"\" loaded");
            }
            else if(ending.equals("shvm")) {
                viewPane.add(filename, new shvm(this,filename));
                setBusy(false,"SHVM \""+filename+"\" loaded");
            }
            else
                setBusy(false,"Unknown File Type");
            viewPane.setSelectedIndex(viewPane.getComponentCount()-1);
        } else
            setBusy(false, "Opening aborted");
    }//GEN-LAST:event_openMenuItemActionPerformed

    private void PopResetAndRunMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_PopResetAndRunMenuItemActionPerformed
        resetAndRunMenuItem.doClick();
}//GEN-LAST:event_PopResetAndRunMenuItemActionPerformed

    private void PopSaveMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_PopSaveMenuItemActionPerformed
        saveMenuItem.doClick();
}//GEN-LAST:event_PopSaveMenuItemActionPerformed

    private void PopCloseMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_PopCloseMenuItemActionPerformed
        closeCurrentMenuItem.doClick();
    }//GEN-LAST:event_PopCloseMenuItemActionPerformed

    private void PopRenameMenuItemActionPerformed(ActionEvent evt) {//GEN-FIRST:event_PopRenameMenuItemActionPerformed
        setBusy(true, "Renaming Machine...");
        String in = JOptionPane.showInputDialog(this,
                                                "Enter a new name for your machine!",
                                                "Rename",
                                                JOptionPane.QUESTION_MESSAGE);
        if(machineExists(in,currentMachine.getClass())) {
            JOptionPane.showConfirmDialog(this,
                                          "Machine \""+in+"\" already exists!",
                                          "Already exists",
                                          JOptionPane.DEFAULT_OPTION,
                                          JOptionPane.ERROR_MESSAGE);
            setBusy(false,"");
            return;
        }
        if(in!=null&&in.trim().length()>0&&in.matches("[A-Za-z0-9. ]*")) {
            File testFile = null;
            if(currentMachine instanceof hvm)
                testFile = new File("machines/"+in+".hvm");
            else if(currentMachine instanceof shvm)
                testFile = new File("machines/"+in+".shvm");
            if(testFile.exists())
                if(JOptionPane.NO_OPTION==JOptionPane.showConfirmDialog(this, 
                                                                        "A machine with the name \""+in+"\"\nalready exists in the directory.\nRename anyway?",
                                                                        "Already exists",
                                                                        JOptionPane.YES_NO_OPTION,
                                                                        JOptionPane.WARNING_MESSAGE)) {
                    setBusy(false,"Renaming aborted");
                    return;
                }
            setBusy(false,"\""+viewPane.getTitleAt(viewPane.getSelectedIndex()).replaceAll("\\x2a", "")+"\" renamed to \""+in+"\"");
            viewPane.setTitleAt(viewPane.getSelectedIndex(), in);
            ((StackMachine)viewPane.getSelectedComponent()).setName(in);
            setChanged(true);
        } else if(in!=null){
            JOptionPane.showConfirmDialog(this, 
                                          "You have to enter a valid name!\n (Only [A-Za-z0-9. ] is allowed)",
                                          "No Name",
                                          JOptionPane.DEFAULT_OPTION,
                                          JOptionPane.ERROR_MESSAGE);
            setBusy(false,"Error renaming Machine");
        } else
            setBusy(false,"");
    }//GEN-LAST:event_PopRenameMenuItemActionPerformed
   
    
    
    //</editor-fold>

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                vm myVM = new vm();
                try {
                    myVM.setIconImage(ImageIO.read(getClass().getResource("/resources/GoToCallingMethod.gif")));
                } catch (IOException ex) {
                    Logger.getLogger(vm.class.getName()).log(Level.SEVERE, null, ex);
                }
                myVM.setVisible(true);
                myVM.hideFocus();
            }
        });
    }
    // <editor-fold defaultstate="collapsed" desc="Variables declaration">
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private JMenuBar MenuBar;
    private JMenuItem PopCloseMenuItem;
    private JMenuItem PopRenameMenuItem;
    private JMenuItem PopResetAndRunMenuItem;
    private JMenuItem PopSaveMenuItem;
    private JPopupMenu PopupMenu;
    private JToolBar ToolBar;
    private JMenuItem aboutMenuItem;
    private JMenuItem asciiInputMenuItem;
    private JMenuItem clearInputMenuItem;
    private JMenuItem closeCurrentMenuItem;
    private JMenuItem copyMenuItem;
    private JMenuItem cutMenuItem;
    private JLabel cycleLimitLabel;
    private JMenuItem helpHVMMenuItem;
    private JMenuItem helpSHVMMenuItem;
    private JMenu jMenu1;
    private JMenu jMenu2;
    private JMenu jMenu3;
    private JMenu jMenu4;
    private JMenu jMenu5;
    private Separator jSeparator1;
    private Separator jSeparator10;
    private Separator jSeparator2;
    private Separator jSeparator3;
    private Separator jSeparator4;
    private Separator jSeparator5;
    private JToolBar.Separator jSeparator6;
    private JToolBar.Separator jSeparator7;
    private JToolBar.Separator jSeparator8;
    private Separator jSeparator9;
    private JMenu lafMenu;
    private static JSpinner maxCycles;
    private JMenuItem newHVMMenuItem;
    private JMenuItem newSHVMMenuItem;
    private JMenuItem numberInputMenuItem;
    private JButton openButton;
    private JMenuItem openMenuItem;
    private JMenuItem pasteMenuItem;
    private JMenuItem propertiesMenuItem;
    private JMenuItem quitMenuItem;
    private JButton redoButton;
    private JMenuItem redoMenuItem;
    private JButton resetAndRunButton;
    private JMenuItem resetAndRunMenuItem;
    private JButton resetButton;
    private JMenuItem resetMenuItem;
    private JButton runButton;
    private JMenuItem runMenuItem;
    private JButton runStepButton;
    private JMenuItem runStepMenuItem;
    private JButton runToCursorButton;
    private JMenuItem runToCursorMenuItem;
    private JButton saveButton;
    private JMenuItem saveMenuItem;
    private JLabel statuslabel;
    private static JSpinner timeout;
    private JLabel timeoutLabel;
    private JButton undoButton;
    private JMenuItem undoMenuItem;
    private JTabbedPane viewPane;
    // End of variables declaration//GEN-END:variables
    //</editor-fold>



    // <editor-fold defaultstate="collapsed" desc="Costum Methods">
    private void closeApp() {
        Object[] options = {"Yes","No","Cancel"};
        int choice = JOptionPane.NO_OPTION;
        setBusy(true,"Closing...");
        for (int i = 0; i < viewPane.getTabCount(); i++) {
            if(viewPane.getTitleAt(i).endsWith("*")) {
                choice = JOptionPane.showOptionDialog(this, //parent
                                                  "Do want to save before quiting?", //message object
                                                  "Quiting..." , //title
                                                  JOptionPane.DEFAULT_OPTION, //use costum options
                                                  JOptionPane.QUESTION_MESSAGE, //message type
                                                  null, //icon
                                                  options, //array of options
                                                  options[0]); //initial value
                break;
            }
        //OptionPane.showConfirmDialog(this, "Do want to save before quiting?","Quiting..." , JOptionPane.YES_NO_CANCEL_OPTION , JOptionPane.QUESTION_MESSAGE);
        }

        switch(choice) {
            case JOptionPane.YES_OPTION :
                for (int i = 0; i < viewPane.getTabCount(); i++) {
                    if(viewPane.getTitleAt(i).endsWith("*")) {
                        ((StackMachine)viewPane.getComponentAt(i)).save();
                    }
                }
            case JOptionPane.NO_OPTION :
                System.exit(0);
            default:
                setBusy(false,"Closing aborted");
        }
    }
    public void setBusy(boolean startIt, String message) {
        broadcastStatus(message);
        setBusy(startIt);
    }

    public void setBusy(boolean startIt) {
        if(startIt && !busy.isRunning()) busy.start();
        else if(!startIt && busy.isRunning()) {
            busy.stop();
            statuslabel.setIcon(idleIcon);
        }        
    }

    private void enableMenus(boolean enable) {
         copyMenuItem.setEnabled(enable);
         cutMenuItem.setEnabled(enable);
         pasteMenuItem.setEnabled(enable);

         closeCurrentMenuItem.setEnabled(enable);

         resetAndRunMenuItem.setEnabled(enable);
         resetAndRunButton.setEnabled(enable);
         runMenuItem.setEnabled(enable);
         runButton.setEnabled(enable);
         runStepMenuItem.setEnabled(enable);
         runStepButton.setEnabled(enable);
         runToCursorMenuItem.setEnabled(enable);
         runToCursorButton.setEnabled(enable);
         resetMenuItem.setEnabled(enable);
         resetButton.setEnabled(enable);

         numberInputMenuItem.setEnabled(enable);
         asciiInputMenuItem.setEnabled(enable);
         clearInputMenuItem.setEnabled(enable);
         if(!enable) {
             setUndo(enable);
             setRedo(enable);
         }
    }

    public void broadcastStatus(String message) {
        statuslabel.setText(message);
    }

    void setUndo(boolean enable) {
        undoMenuItem.setEnabled(enable);
        undoButton.setEnabled(enable);
    }

    void setRedo(boolean enable) {
        redoMenuItem.setEnabled(enable);
        redoButton.setEnabled(enable);
    }

    void setChanged(boolean changed) {
        String title;
        if(viewPane.getTabCount()!=0)
            title = viewPane.getTitleAt(viewPane.getSelectedIndex());
        else
            title = "";
        if(changed && !title.endsWith("*"))
            viewPane.setTitleAt(viewPane.getSelectedIndex(), title+"*");
        if(!changed && title.endsWith("*"))
            viewPane.setTitleAt(viewPane.getSelectedIndex(), title.replaceAll("\\x2a", ""));
        saveMenuItem.setEnabled(changed);
        saveButton.setEnabled(changed);
    }

    private boolean machineExists(String in, Class aClass) {
        for (int i = 0; i < viewPane.getTabCount(); i++) {
            if(viewPane.getComponentAt(i).getClass().equals(aClass) &&
                    ((StackMachine)viewPane.getComponentAt(i)).getName().equals(in))
                return true;
        }
        return false;
    }
    
    static public int getMaxCycles() {
        return ((SpinnerNumberModel)maxCycles.getModel()).getNumber().intValue();
    }

    static public long getTimeout() {
        return ((SpinnerNumberModel)timeout.getModel()).getNumber().longValue();
    }

    private void hideFocus() {
        cycleLimitLabel.requestFocusInWindow();
    }

    // </editor-fold>
}
